iT邦幫忙

0

Day 22|非同步程式設計(async / await)與資料表關聯

c#
  • 分享至 

  • xImage
  •  

今日學習目標

  • 理解同步與非同步程式的差別
  • 能夠解釋 async、await、Task 的作用
  • 了解 EF Core 為什麼使用 ToListAsync() 和 SaveChangesAsync()
  • 認識主鍵(PK)與外鍵(FK)
  • 理解一對多(One-to-Many)資料表關係
  • 建立 Category 模型並認識 EF Core 關聯設定
  • 完成資料表關聯的練習

什麼是 async 與 await

同步寫法:

public List<TaskItem> GetAll()
{
    return _db.Tasks.ToList();
}

執行資料庫查詢時,目前的執行緒需要等待操作完成,才會繼續往下執行。
非同步寫法:

public async Task<List<TaskItem>> GetAllAsync()
{
    return await _db.Tasks.ToListAsync();
}

當資料庫查詢正在等待 I/O 完成時,執行緒通常不需要一直被占用,可以用來處理其他工作。

Task 和 Task T 的差別

Task:代表非同步操作,不回傳特定資料。
Task T :代表非同步操作,完成後會回傳 T 型別的資料。

什麼是資料表關聯

https://ithelp.ithome.com.tw/upload/images/20261023/20184430TQuqadmuXb.png
主鍵 PK 與外鍵 FK
Primary Key(主鍵):唯一識別一筆資料,例如 Categories.Id。
Foreign Key(外鍵):用來建立資料表之間的關聯,例如 Tasks.CategoryId 指向 Categories.Id。

建立 Category 模型

繼續使用昨日專案
新增 Category.cs
在Models建立新檔案 Category.cs

using System.Collections.Generic;

namespace TaskFlow3.Api.Models
{
    public class Category
    {
        public int Id { get; set; }

        public string Name { get; set; } = "";

        public List<TaskItem> Tasks { get; set; } = new();
    }
}

修改 TaskItem.cs

namespace TaskFlow3.Api.Models
{
    public class TaskItem
    {
        public int Id { get; set; }

        public string Title { get; set; } = "";

        public bool IsCompleted { get; set; }

        // 外鍵:任務所屬的分類編號
        public int? CategoryId { get; set; }

        // 導覽屬性:任務所屬的分類
        public Category? Category { get; set; }
    }
}

修改 TaskFlowDbContext.cs

using Microsoft.EntityFrameworkCore;
using TaskFlow3.Api.Models;

namespace TaskFlow3.Api.Data
{
    public class TaskFlowDbContext : DbContext
    {
        public TaskFlowDbContext(
            DbContextOptions<TaskFlowDbContext> options
        ) : base(options)
        {
        }

        // 任務資料表
        public DbSet<TaskItem> Tasks { get; set; } = null!;

        // 分類資料表
        public DbSet<Category> Categories { get; set; } = null!;

        protected override void OnModelCreating(
            ModelBuilder modelBuilder)
        {
            // Tasks 資料表
            modelBuilder.Entity<TaskItem>(entity =>
            {
                entity.ToTable("Tasks");

                entity.HasKey(t => t.Id);

                entity.Property(t => t.Id)
                      .ValueGeneratedOnAdd();

                entity.Property(t => t.Title)
                      .IsRequired();

                entity.Property(t => t.IsCompleted)
                      .IsRequired();

                // 一個分類可以包含多筆任務
                entity.HasOne(t => t.Category)
                      .WithMany(c => c.Tasks)
                      .HasForeignKey(t => t.CategoryId)
                      .IsRequired(false);
            });

            // Categories 資料表
            modelBuilder.Entity<Category>(entity =>
            {
                entity.ToTable("Categories");

                entity.HasKey(c => c.Id);

                entity.Property(c => c.Name)
                      .IsRequired()
                      .HasMaxLength(100);
            });
        }
    }
}

建立 Migration 更新資料庫

專案資料夾執行:dotnet build
建立新的 Migration:dotnet ef migrations add AddCategories
更新資料庫:dotnet ef database update


*提醒邦友,使用第三方服務/API 時,請務必評估資安風險與隱私保護
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言